package com.ruoyi.iot.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.extra.pinyin.PinyinUtil;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.iot.constant.DbDataTypeEnum;
import com.ruoyi.iot.constant.MateConstant;
import com.ruoyi.iot.domain.FacDevicesMonitorParam;
import com.ruoyi.iot.domain.FacDevicesType;
import com.ruoyi.iot.domain.MetaDataDict;
import com.ruoyi.iot.mapper.DbMapper;
import com.ruoyi.iot.service.DbService;
import com.ruoyi.iot.service.IFacDevicesMonitorParamService;
import com.ruoyi.iot.service.IFacDevicesTypeService;
import com.ruoyi.iot.util.SqlUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.iot.mapper.FacDevicesMonitorMapper;
import com.ruoyi.iot.domain.FacDevicesMonitor;
import com.ruoyi.iot.service.IFacDevicesMonitorService;

/**
 * 设备类型监测Service业务层处理
 * 
 * @author rww
 * @date 2024-06-19
 */
@Service
public class FacDevicesMonitorServiceImpl implements IFacDevicesMonitorService 
{
    @Autowired
    private FacDevicesMonitorMapper facDevicesMonitorMapper;

    @Autowired
    private IFacDevicesTypeService facDevicesTypeService;

    @Autowired
    private DbService dbService;

    @Autowired
    private IFacDevicesMonitorParamService facDevicesMonitorParamService;
    /**
     * 查询设备类型监测
     * 
     * @param id 设备类型监测主键
     * @return 设备类型监测
     */
    @Override
    public FacDevicesMonitor selectFacDevicesMonitorById(Long id)
    {
        return facDevicesMonitorMapper.selectFacDevicesMonitorById(id);
    }

    /**
     * 查询设备类型监测列表
     * 
     * @param facDevicesMonitor 设备类型监测
     * @return 设备类型监测
     */
    @Override
    public List<FacDevicesMonitor> selectFacDevicesMonitorList(FacDevicesMonitor facDevicesMonitor)
    {
        return facDevicesMonitorMapper.selectFacDevicesMonitorList(facDevicesMonitor);
    }

    /**
     * 新增设备类型监测
     * 
     * @param facDevicesMonitor 设备类型监测
     * @return 结果
     */
    @Override
    public int insertFacDevicesMonitor(FacDevicesMonitor facDevicesMonitor)
    {
        facDevicesMonitor.setId(IdUtil.getSnowflakeNextId());
        return facDevicesMonitorMapper.insertFacDevicesMonitor(facDevicesMonitor);
    }

    /**
     * 修改设备类型监测
     * 
     * @param facDevicesMonitor 设备类型监测
     * @return 结果
     */
    @Override
    public int updateFacDevicesMonitor(FacDevicesMonitor facDevicesMonitor)
    {
        return facDevicesMonitorMapper.updateFacDevicesMonitor(facDevicesMonitor);
    }

    /**
     * 批量删除设备类型监测
     * 
     * @param ids 需要删除的设备类型监测主键
     * @return 结果
     */
    @Override
    public int deleteFacDevicesMonitorByIds(Long[] ids)
    {
        return facDevicesMonitorMapper.deleteFacDevicesMonitorByIds(ids);
    }

    /**
     * 删除设备类型监测信息
     * 
     * @param id 设备类型监测主键
     * @return 结果
     */
    @Override
    public int deleteFacDevicesMonitorById(Long id)
    {
        return facDevicesMonitorMapper.deleteFacDevicesMonitorById(id);
    }

    @Override
    public int setMonitor(FacDevicesMonitor facDevicesMonitor) {
        //创表规则:fac_data_型号编码_{父级监测类型名称简拼}_监测类型名称简拼
        //根据名称获取简拼
        String tableDesc = facDevicesMonitor.getTableDesc();
        //判断是否存在相同名字
        if(hasSameName(facDevicesMonitor)>0){//已存在相同名字
            return  -2;
        }
        String tableSuffix = PinyinUtil.getFirstLetter(tableDesc, "").replace("-", "_").replace(".", "");
        facDevicesMonitor.setTablePrefix(tableSuffix);
        //根据typeid获取type信息
        FacDevicesType typeInf=facDevicesTypeService.selectFacDevicesTypeById(facDevicesMonitor.getTypeId());
        if(ObjectUtil.isEmpty(typeInf)){
            return -1;//设备类型不存在;
        }
        String tableName="fac_data_"+typeInf.getCode()+"_";
        //判断是否有父级节点
        if(ObjectUtil.isNotEmpty(facDevicesMonitor.getPid())){
            //获取父级节点信息
            FacDevicesMonitor pInfo=selectFacDevicesMonitorById(facDevicesMonitor.getPid());
            if(ObjectUtil.isNotEmpty(pInfo)){
                tableName+=pInfo.getTablePrefix()+"_";
            }
        }
        tableName+=tableSuffix;
        facDevicesMonitor.setTableName(tableName);
        //判断是否存在对应的数据表

        int hasTable=dbService.existTable(tableName);
        //如果存在则返回该表已存在
        if(hasTable>0){
            return 2;//2表示表已存在
        }
        //如果不存在创建表，插入新增记录,判断是表存储还是字段存储
        List<MetaDataDict> fieldlist = new ArrayList<>();
        if(MateConstant.DATA_FIELD.equals(facDevicesMonitor.getDataClass()) ){//创建字段数据表
            fieldlist.add(new MetaDataDict("id", "主键", DbDataTypeEnum.LONG, true));
            fieldlist.add(new MetaDataDict("device_id", "设备id", DbDataTypeEnum.LONG));
            fieldlist.add(new MetaDataDict("field", "监测参数", DbDataTypeEnum.STRING));
            fieldlist.add(new MetaDataDict("field_value", "监测值", DbDataTypeEnum.STRING));
            fieldlist.add(new MetaDataDict("monitoring_time", "监测时间", DbDataTypeEnum.DATE));
            fieldlist.add(new MetaDataDict("create_time", "创建时间", DbDataTypeEnum.DATE));
        }
        else{//创建Table 数据表
            fieldlist.add(new MetaDataDict("id", "主键", DbDataTypeEnum.LONG, true));
            fieldlist.add(new MetaDataDict("device_id", "设备id", DbDataTypeEnum.LONG));
            fieldlist.add(new MetaDataDict("monitoring_time", "监测时间", DbDataTypeEnum.DATE));
            if (ObjectUtil.isNotEmpty(facDevicesMonitor.getPid())) {
                fieldlist.add(new MetaDataDict("data_id", "运行id", DbDataTypeEnum.LONG));
            }
        }
        //获取创建表sql语句
        String createSql= SqlUtils.buildCreateGisSql(tableName,fieldlist);
        //创建表
        dbService.createTable(createSql);
//        //插入类型记录
        insertFacDevicesMonitor(facDevicesMonitor);
        return 1;
    }

    @Override
    public int hasSameName(FacDevicesMonitor facDevicesMonitor) {
        return facDevicesMonitorMapper.hasSameCode(facDevicesMonitor);
    }

    @Override
    public int setMonitorParam(FacDevicesMonitor facDevicesMonitor) {
        String tableName=facDevicesMonitor.getTableName();
        List<FacDevicesMonitorParam> newList=facDevicesMonitor.getFieldList();
        //获取类型当前已有的字段
        Long monitorId=facDevicesMonitor.getId();
        //根据monitorId获取list
        FacDevicesMonitorParam param=new FacDevicesMonitorParam();
        param.setMonitorId(monitorId);
        List<FacDevicesMonitorParam> list=facDevicesMonitorParamService.selectFacDevicesMonitorParamList(param);
        Map<String,FacDevicesMonitorParam> oldmap= list.stream().collect(Collectors.toMap(FacDevicesMonitorParam::getField, Function.identity()));
        Map<String,FacDevicesMonitorParam> newmap= newList.stream().collect(Collectors.toMap(FacDevicesMonitorParam::getField, Function.identity()));
        Map<Long,FacDevicesMonitorParam> oldMapKey= list.stream().collect(Collectors.toMap(FacDevicesMonitorParam::getId, Function.identity()));
        List<FacDevicesMonitorParam> updateNewField=new ArrayList<>();
        for(FacDevicesMonitorParam currFiled:newList){
            if(ObjectUtil.isNotEmpty(currFiled.getId()) ){
                updateNewField.add(currFiled);
            }
        }
        Map<Long,FacDevicesMonitorParam> newMapKey= updateNewField.stream().collect(Collectors.toMap(FacDevicesMonitorParam::getId, Function.identity()));
        //比较新增、修改、删除了那些字段
        List<MetaDataDict> addlist=new ArrayList<>();
        List<MetaDataDict> updatelist=new ArrayList<>();
        List<MetaDataDict> deletelist=new ArrayList<>();

        for(FacDevicesMonitorParam currField:newList){
            //旧字段中是否存在
            DbDataTypeEnum typeEnum= DbDataTypeEnum.getType(currField.getFieldType());
            FacDevicesMonitorParam properties=oldmap.get(currField.getField());
            FacDevicesMonitorParam propertieskey=oldMapKey.get(currField.getId());
            if(ObjectUtil.isNotEmpty(properties) || ObjectUtil.isNotEmpty(propertieskey)){
                //存在判断是否一致，不一致则修改
                //判断是否一致
                if(!currField.equals(properties) && !currField.getField().equals("id")){
                    String oldField="";
                    updatelist.add(new MetaDataDict(currField.getField(),currField.getFieldName(),typeEnum,propertieskey.getField()));
                    //修改字段表中字段记录（properties）
                    facDevicesMonitorParamService.updateFacDevicesMonitorParam(currField);
                }
            }
            else {
                //不存在则新增
                if(!currField.getField().equals("id")){
                    addlist.add(new MetaDataDict(currField.getField(),currField.getFieldName(),typeEnum));
                    //新增修改字段表记录(currField)
                    facDevicesMonitorParamService.insertFacDevicesMonitorParam(currField);
                }
            }
        }
        for(FacDevicesMonitorParam currField:list){
            DbDataTypeEnum typeEnum= DbDataTypeEnum.getType(currField.getFieldType());
            FacDevicesMonitorParam properties=newmap.get(currField.getField());
            FacDevicesMonitorParam propertiesKey=newMapKey.get(currField.getId());
            if(!ObjectUtil.isNotEmpty(properties) && !currField.getField().equals("id") && !ObjectUtil.isNotEmpty(propertiesKey)){
                //进行删除
                //字段没有对应的记录则可以删除该字段
                String sql = "select count(0) from " + tableName +" where field='"+ currField.getField()+"'";
                int tnum = dbService.count(sql);
                if(tnum>0) {
                    String sql1="select count(DISTINCT "+ currField.getField()+") from "+ tableName+" where "+ currField.getField()+" is not null ";
                    int num=dbService.count(sql1);
                    if (num < 1) {
                        deletelist.add(new MetaDataDict(currField.getField(), currField.getFieldName(), typeEnum));
                        facDevicesMonitorParamService.deleteFacDevicesMonitorParamById(currField.getId());
                    }
                }
            }
        }

        if(ObjectUtil.isNotEmpty(addlist)){
            String sql= SqlUtils.buildAddColumnSql(tableName,addlist);
            dbService.update(sql);
        }
        if(ObjectUtil.isNotEmpty(updatelist)){
            String sql= SqlUtils.buildUpdateColumnSql(tableName,updatelist);
            dbService.update(sql);
        }
        if(ObjectUtil.isNotEmpty(deletelist)){
            String sql= SqlUtils.buildDropColumnSql(tableName,deletelist);
            dbService.update(sql);
        }
        return 1;
    }

}
